(function($) {
  // page params
  var urlParams = location.search.slice(1).split('&').filter(Boolean)
    .map(function(keyval) { return keyval.split('='); })
    .reduce(function(res, keyval) {
      res[keyval[0]] = keyval[1];
      return res;
    }, {});
  console.log('urlParams', urlParams);
  var tab = urlParams.tab || 'profile';
  var env = urlParams.env || '';
  var city = urlParams.city || 'Amsterdam';

  var dataUrl = env === 'devo' ?
    'https://oss.matrixsci.cn/ned/data/data-test.json' :
    'https://oss.matrixsci.cn/ned/data/data.json';

  // configs
  var cities = [
    { id: 'Amsterdam', name: '阿姆斯特丹' },
    { id: 'Rotterdam', name: '鹿特丹' },
    { id: 'Den-Haag', name: '海牙' },
    { id: 'Utrecht', name: '乌特勒支'},
    { id: 'hidden-gems', name: '私藏宝地' }
  ]

  var finalItemList = [];

  function removeUnknownChars(str) {
    str = str || '';
    return str.replace('\u0008', '') // \b
      .replace(/\u0009/g, '\t')
      .replace(/\u000A/g, '\n')
      .replace(/\u000B/g, '') // \v
      .replace(/\u000C/g, '') // \f
      .replace(/\u000D/g, '') // \r
      .replace(/\u2028/g, '') // 行分隔符
      .replace(/\u2029/g, '') // 段落分隔符
      .replace(/\uFEFF/g, '') // 字节顺序标记
  }

  function values(obj) {
    return Object.keys(obj).map(function(key) { return obj[key]; });
  }
  function highlight(text, searchWord) {
    if (!searchWord) { return text; }
    return String(text||'').replace(new RegExp('('+searchWord+')', 'i'), '<span class="highlight">$1</span>');
  }
  function cookItem(item, options) {
    options = options || {};

    item.id = Number(item.id);
    item.top = !!item.top;
    item.coupon = !!item.coupon;
    item.wifi = /wifi|wi-fi/i.test(item.service);
    item.alipay = /支付宝/.test(item.service);
    item.wxpay = /微信支付/.test(item.service);
    item.audioGuide = /语音导览/.test(item.service);
    // item.ticket = /网上订票/.test(item.service);

    if (item.coupon) {
      item.couponId = item.couponId || (item.id + "");
    } else {
      item.couponId = null;
    }

    item.cityName = (cities.find(city => city.id === item.city) || { name: item.city }).name;
    if (!options.ignoreImages) {
      item.leftIcon = 'http://oss.matrixsci.cn/ned/'+item.id+'-4.jpg?t='+(item.lastUpdateTime||'');
      item.banner = 'http://oss.matrixsci.cn/ned/'+item.id+'-1.jpg?t='+(item.lastUpdateTime||'');
      item.inner1 = 'http://oss.matrixsci.cn/ned/'+item.id+'-2.jpg?t='+(item.lastUpdateTime||'');
      item.inner2 = 'http://oss.matrixsci.cn/ned/'+item.id+'-3.jpg?t='+(item.lastUpdateTime||'');

      item.couponPopup = 'http://oss.matrixsci.cn/ned/coupon/popup/'+item.couponId+'.png?t='+(item.lastUpdateTime||'');
      item.couponListItem = 'http://oss.matrixsci.cn/ned/coupon/listitem/'+item.couponId+'.png?t='+(item.lastUpdateTime||'');
      item.couponDetail = 'http://oss.matrixsci.cn/ned/coupon/detail/'+item.couponId+'.png?t='+(item.lastUpdateTime||'');
    }
    return item;
  }
  function getNextId() {
    var idInfoText = localStorage.getItem('idInfo') || "{}";
    var idInfo = JSON.parse(idInfoText);
    return idInfo.id;
  }
  function getNewItem() {
    return {
      "id": getNextId(),
      "title": "",
      "enTitle": "",
      "label": "",
      "gifts": false,
      "ticket": false,
      "audioGuide": false,
      "latitude": 52.383978,
      "longitude": 4.902404,
      "city": "Amsterdam",
      "category": "attractions",
      "summary": "",
      "recommendation": "",
      "coupon": false,
      "couponId": null,
      "service": "Wi-Fi",
      "address": "",
      "openHour": "全天",
      "price": "免费",
      "website": "",
      "telephone": "+31(0)",
      "wifi": true,
      "alipay": false,
      "wxpay": false,
      "leftIcon": 'images/left-icon.jpg',
      "banner": 'images/banner.jpg',
      "inner1": 'images/inner1.jpg',
      "inner2": 'images/inner2.jpg',
      "couponPopup": null,
      "couponListItem": null,
      "couponDetail": null,
    };
  }
  function getNewArticle() {
    return {
      title: '',
      index: 0,
      content: '示例：\n\n这是{b:加粗文字}\n这是{t:蓝色文字}\n两个字母一起用，就成了{tb:蓝色加粗}或者{bt:加粗蓝色}\n{c:居中的文字}\n{cb:居中的加粗文字}\n{ctp:居中的蓝色文字，上下加一些padding}\n{cbt:居中的加粗蓝色文字}\n{img:1}\n比普通的字大一些的{l:大号文字}\n{lcbt:大号的居中标题}',
      images: [],
    };
  }
  // var cityId = urlParams['city'] || 'Amsterdam';
  var app = new Vue({
    el: '#app',
    data: {
      env: env, // 'devo' means testing env, '' means prod env
      loading: false,
      loadingMessage: '',
      cities: cities,
      // cityId: cityId,
      tab: tab,
      city: city,
      itemlist: [],
      categoryMap: {
        'attractions': '景点',
        'shopping': '购物',
        'restaurants': '餐厅',
        'hotels': '酒店',
        'nightlife': '夜生活',
        'whats-on': '娱乐项目',
      },
      page: 1,
      pageSize: 30,
      searchWord: '',
      filterTitle: '',
      filterId: '',
      filterCity: '',
      filterCategory: '',
      selectedItemId: null,
      iconInfoList: [
        { field: 'coupon', text: '打折券', icon: './images/icon-discount.png' },
        { field: 'wifi', text: 'WiFi', icon: './images/icon-wifi.png' },
        { field: 'ticket', text: '购票', icon: './images/icon-ticket.png' },
        { field: 'gifts', text: '礼物', icon: './images/icon-gifts.png' },
        // { field: 'sale', text: '售票', icon: './icon-sale.png' },
        { field: 'audioGuide', text: '语音导览', icon: './images/icon-audio-guide.png' },
        { field: 'alipay', text: '支付宝', icon: './images/icon-alipay.png' },
        { field: 'wxpay', text: '微信支付', icon: './images/icon-wxpay.png' },
      ],
      editing: false,
      isNew: false,
      editingCoupon: false,
      newItem: getNewItem(),
      disableCreateBtn: false,
      sortField: 'id',
      sortMethod: 'desc',
      message: '',
      totalImageUpload: 0,
      selectedArticle: null,
      articleList: [],
    },
    computed: {
      filteredItemlist: function() {
        var that = this;
        var sortFunction = function(item1, item2) {
          if (item1.top !== item2.top) {
            return item2.top - item1.top;
          }
          if (that.sortField) {
            if (item1[that.sortField] == item2[that.sortField]) {
              return 0;
            }

            var res = item1[that.sortField] < item2[that.sortField] ? -1 : 1;
            if (that.sortField === 'title') {
              res = item1[that.sortField].localeCompare(item2[that.sortField], 'zh');
            }
            return that.sortMethod === 'asc' ? res : -res;
          }
        };
        return this.itemlist
          .filter(function(item) { return !that.filterId || (item.id+'').indexOf(that.filterId) >= 0 })
          .filter(function(item) {
            return !that.filterTitle || item.title.toLowerCase().indexOf(that.filterTitle.toLowerCase()) >= 0
          })
          .filter(function(item) { return !that.filterCity || item.city === that.filterCity })
          .filter(function(item) { return !that.filterCategory || item.category === that.filterCategory })
          .sort(sortFunction)
      },
      itemlistForDisplay: function() {
        var start = (this.page - 1) * this.pageSize;
        var end = start + this.pageSize;
        var that = this;
        var topBadge = ' <span class="label label-success">置顶</span>';
        return this.filteredItemlist
          .slice(start, end)
          .map(function(item) {
            return $.extend({}, item, {
              title: highlight(item.title, that.filterTitle),
              // id: highlight(item.id, that.filterId), // + (item.top ? topBadge : ''),
              highlightedId: highlight(item.id, that.filterId) + (item.top ? topBadge : ''),
            })
          });
      },
      maxPage: function() {
        // console.log('maxPage calculation', this.filteredItemlist.length, this.pageSize, this.filteredItemlist.length / this.pageSize);
        var _maxPage = Math.ceil(this.filteredItemlist.length / this.pageSize);
        if (this.page > _maxPage) {
          this.page = 1;
        }
        return _maxPage;
      },
      selectedItem: function() {
        if (this.selectedItemId === null) {
          return null;
        }
        if (this.selectedItemId === getNextId()) {
          var item = cookItem(this.newItem, { ignoreImages: true, ignoreCoupon: true });
          console.log('heihei, return new item', this.selectedItemId, item);
          return item;
        }
        var that = this;
        var item = this.itemlist.find(function(item) { return item.id === that.selectedItemId });
        if (item) {
          cookItem(item, { ignoreCoupon: true });
        }
        console.log('old item!!!!!!!', that.selectedItemId, item);
        return item;
      },
      selectedArticleContentHtml: function() {
        var pList = this.selectedArticle.content.split(/\r\n|\r|\n/);
        var that = this;
        return pList.map(p => {
          return p.replace(/\{([tcblpPT]+):([^\}]+)\}/g, function(originText, formatLetters, text) {
            var classes = (formatLetters||'').split('').join(' ');
            return '<span class="'+classes+'">'+text+'</span>';
          }).replace(/\{img:(\d+)\}/g, function(originText, imageIndex) {
            var index = Number(imageIndex);
            // if (index < that.selectedArticle.images.length) {
              return '<div class="article-img c"><div><img src="' + that.getArticleImageUrl(index) + '"/></div></div>';
            // }
            // return originText;
          })
        }).map(p => '<div>'+(p||'&nbsp;')+'</div>').join('\n');
      },
      selectedArticleTitleHtml: function() {
        return this.selectedArticle.title.replace(/\r\n|\r|\n/g, '<br/>');
      }
    },
    methods: {
      cx: function() {
        var classList = Array.prototype.slice.call(arguments);
        return classList.filter(Boolean);
      },
      sort: function(field) {
        if (this.sortField === field) {
          this.sortMethod = this.sortMethod === 'asc' ? 'desc' : 'asc';
        } else {
          this.sortField = field;
          this.sortMethod = 'asc';
        }
      },
      add: function() {
        this.newItem = getNewItem();
        this.selectedItemId = getNextId();
        this.editing = true;
      },
      goPrevPage: function() {
        this.page = Math.max(1, this.page-1);
      },
      goNextPage: function() {
        this.page = Math.min(this.maxPage, this.page+1);
      },
      cancelEdit: function() {
        var that = this;
        var originItem = finalItemList.find(function(item) { return item.id === that.selectedItem.id });
        $.extend(this.selectedItem, originItem);
        this.editing = false;
      },
      br: function(text) {
        return text.replace(/[\r\n]+/g, '<br/>');
      },
      getNewItem: getNewItem,
      fileInput: function(e, field) {
        var url = window.URL.createObjectURL(e.target.files[0]);
        this.selectedItem[field] = url;
        this.selectedItem[field+'File'] = e.target.files[0];
        console.log('fileInput', e, field, this.selectedItem);
      },
      showLoading: function(message) {
        this.loading = true;
        this.loadingMessage = message;
      },
      hideLoading: function() {
        this.loading = false;
        this.loadingMessage = '';
      },
      remove: function(id) {
        if (confirm('确认删除id为'+id+'的profile?')) {
          var index = this.itemlist.findIndex(function(item) { return item.id == id });
          console.log('remove', index);
          if (index >= 0) {
            var itemlist = this.itemlist.slice();
            itemlist.splice(index, 1);

            var that = this;
            this.showLoading('正在删除...');
            this._uploadData(itemlist, function() {
              that.hideLoading();
              that.itemlist.splice(index, 1);
              that.message = "删除成功";
            });
          }
        }
      },
      save: function() {
        this.showLoading('正在保存...');
        var that = this;

        var imageUploadCount = 0;
        var __imageUploaded = function(res) {
          ++imageUploadCount;
          // console.log('__imageUploaded', imageUploadCount, that.totalImageUpload);
          that.showLoading('上传图片 '+(imageUploadCount) + '/' + that.totalImageUpload);
          if (imageUploadCount < that.totalImageUpload) {
            return;
          }
          that.totalImageUpload = 0;

          var lastUpdateTime = new Date().getTime();
          var itemlist = $.extend(true, [], that.itemlist);

          var item = itemlist.find(function(item) { return item.id == that.selectedItem.id });
          if (!item) {
            itemlist.push($.extend({}, that.selectedItem));
          } else {
            $.extend(item, that.selectedItem);
          }
          (item || that.selectedItem).lastUpdateTime = lastUpdateTime;

          var fieldsToDelete = ['leftIcon', 'banner', 'inner1', 'inner2',
            'couponPopup', 'couponListItem', 'couponDetail'];
          itemlist.forEach(function(item) {
            fieldsToDelete.forEach(function(field) {
              delete item[field];
              delete item[field+'File'];
            })
          })

          // console.log('itemlist to upload', itemlist);
          that.showLoading('保存数据...');
          that._uploadData(itemlist, function() {
            that.editing = false;
            that.hideLoading();

            var item = that.itemlist.find(function(item) { return item.id == that.selectedItem.id });
            if (!item) {
              that.itemlist.push($.extend({}, that.selectedItem));
            } else {
              $.extend(item, that.selectedItem);
            }
            (item || that.selectedItem).lastUpdateTime = lastUpdateTime;
            location.href = '#';
            that.message = '保存成功！';

            var idInfoText = localStorage.getItem('idInfo') || "{}";
            var idInfo = JSON.parse(idInfoText);
            if (that.selectedItem.id == idInfo.id) {
              localStorage.setItem('idInfo', '');
              updateNextId();
            }
            console.log('idInfo', idInfoText, idInfo);
          });
        }

        this._uploadImage('leftIcon', this.selectedItem.id+'-4.jpg', __imageUploaded);
        this._uploadImage('banner', this.selectedItem.id+'-1.jpg', __imageUploaded);
        this._uploadImage('inner1', this.selectedItem.id+'-2.jpg', __imageUploaded);
        this._uploadImage('inner2', this.selectedItem.id+'-3.jpg', __imageUploaded);
        this._uploadImage('couponPopup', 'coupon/popup/' + this.selectedItem.id+'.png', __imageUploaded);
        this._uploadImage('couponListItem', 'coupon/listitem/' + this.selectedItem.id+'.png', __imageUploaded);
        this._uploadImage('couponDetail', 'coupon/detail/' + this.selectedItem.id+'.png', __imageUploaded);
      },
      _uploadData: function(itemlist, success) {
        $.ajax({
          url: dataUrl,
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
          },
          data: removeUnknownChars(JSON.stringify({itemlist: itemlist}, 0, 2)),
          success: function() { success(); }
        })
      },
      _uploadImage: function(field, remoteName, success) {
        this.totalImageUpload++;
        if (!this.selectedItem[field] || !this.selectedItem[field+'File']) {
          setTimeout(function() { success(true) }, 0);
          return;
        }

        var file = this.selectedItem[field+'File'];
        var ext = file.name.split('.').slice(-1)[0];

        $.ajax({
          url: 'https://oss.matrixsci.cn/ned/'+remoteName, //+ext,
          method: 'PUT',
          headers: {
            'Content-Type': file.type,
          },
          processData: false,
          data: file,
          success: function(){ success(true) },
        })
      },
      addArticleImages: function(e) {
        var that = this;
        var images = Object.values(e.target.files).map(function(file) {
          return {
            url: URL.createObjectURL(file),
            file: file,
          }
        })
        that.selectedArticle.images = that.selectedArticle.images.concat(images);
        that.selectedArticle.imageCount = images.length;
      },
      getNewArticle: getNewArticle,
      editArticleImage: function(e) {
        var index = e.target.dataset.index;
        var image = this.selectedArticle.images[index];
        var file = e.target.files[0];
        console.log('editArticleImage', e, index, image, file);
        image.url = URL.createObjectURL(file);
        image.file = file;
      },
      addArticle: function() {
        this.editing = true;
        this.selectedArticle = getNewArticle();
        this.selectedArticle.index = this.articleList.length;
      },
      editArticle: function(article) {
        this.editing = true;
        this.selectedArticle = $.extend(true, {}, article);
        var that = this;
        setTimeout(function() {
          that.updateTextAreaHeight({ target: $('.article-source')[0] });
        }, 100);
      },
      cancelEditArticle: function() {
        this.editing = false;
        this.selectedArticle = null;
      },
      saveArticle: function() {
        var index = this.selectedArticle.index;
        // this.selectedArticle.imageCount = this.selectedArticle.images.length;
        if (index < this.articleList.length) {
          this.articleList[index] = this.selectedArticle;
        } else {
          this.articleList.push(this.selectedArticle);
        }

        var articleList = $.extend(true, [], this.articleList).map(a => {
          delete a.images;
          delete a.index;
          return a;
        });
        console.log('saved article', articleList, JSON.stringify(articleList, 0, 2));

        var that = this;
        this.showLoading('正在保存文章...');
        $.ajax({
          url: 'https://oss.matrixsci.cn/ned/data/our-picks/'+this.city+'.json',
          type: 'PUT',
          headers: {
            'Content-Type': 'application/json',
          },
          data: removeUnknownChars(JSON.stringify({ itemlist: articleList }, 0, 2)),
          success: function() {
            that.editing = false;
            that.isNew = false;
            that.message = '保存成功';
          }
        }).always(this.hideLoading);
      },
      selectArticle: function(article) {
        this.selectedArticle = $.extend(true, {}, article);
      },
      getArticleImageUrl: function(index) {
        return 'http://oss.matrixsci.cn/ned/our-picks/'+this.city+
          '/'+(this.selectedArticle.index+1)+
          '/'+index+'.jpg';
      },
      updateTextAreaHeight: function(e) {
        $(e.target).css('height', (e.target.scrollHeight) + 'px');
      },
      moveUp: function(article) {
        var that = this;
        var index = this.articleList.findIndex(function(item) { return item.index === article.index; });
        if (index === 0) {
          return;
        }
        this.articleList.splice(index, 2, this.articleList[index-1], this.articleList[index]);
      },
      moveDown: function(article) {
        var that = this;
        var index = this.articleList.findIndex(function(item) { return item.index === article.index; });
        if (index === this.articleList.length-1) {
          return;
        }
        this.articleList.splice(index, 2, this.articleList[index+1], this.articleList[index]);
      }
    }, //methods
  });
  window.app = app;

  /*
  这个 https://oss.matrixsci.cn/ned/data/id-info.json 里面存了下一个id应该是多少。
  页面首次加载的时候，会更新里面的id++，然后在本地缓存中记录下来。添加profile的时候会使用++后的id。
  */
  function updateNextId() {
    //如果本地缓存中有就不用请求了。
    var idInfoText = localStorage.getItem('idInfo');
    if (!idInfoText) {
      app.disableCreateBtn = true;
      $.getJSON('https://oss.matrixsci.cn/ned/data/id-info.json', function(res) {
        do {
          res.id++;
          //嗯。由于某种历史原因，存在一些需要跳过的id。我们在自增id的时候需要判断一下id是否需要跳过。
        } while(res.skipIds.includes(res.id));

        //由于是跨域请求，浏览器会首先产生一个OPTION请求，然后接下来才是PUT。
        $.ajax({
          url: 'https://oss.matrixsci.cn/ned/data/id-info.json',
          method: 'PUT',
          headers: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify(res),
          success: function() {
            localStorage.setItem('idInfo', JSON.stringify(res));
            app.disableCreateBtn = false;
            app.newItem = getNewItem();
          }
        })
      })
    }
  }

  if (tab === 'profile') {
    app.showLoading("Loading...");
    $.getJSON(dataUrl, function(res) {
      // console.log('Amsterdam.json', res);
      res.itemlist.forEach(cookItem)
      finalItemList = $.extend(true, [], res.itemlist);
      app.itemlist = $.extend(true, [], res.itemlist);

      let maxId = 0;
      res.itemlist.forEach(function(item) {
        if (item.id > 100000) {
          console.warn('should skip id', item.id);
        } else {
          maxId = Math.max(maxId, Number(item.id));
        }
      })
      console.log('maxId', maxId);
    }).always(app.hideLoading);

    updateNextId();
  } else if (tab === 'our-picks') {
    app.showLoading("Loading...");
    $.getJSON('https://oss.matrixsci.cn/ned/data/our-picks/'+city+'.json', function(res) {
      // console.log('res', res);
      res.itemlist.forEach((item, index) => {
        item.index = index;
      })
      finalItemList = $.extend(true, [], res.itemlist);
      app.articleList = $.extend(true, [], res.itemlist);
      // app.articleList = res.itemlist;
      // console.log('maxId', maxId);
    }).always(app.hideLoading);
  }

})(jQuery);
